package org.myspringmvc.web.servlet.mvc.method.annotation;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.myspringmvc.util.ObjectUtil;
import org.myspringmvc.web.bind.annotation.RequestMapping;
import org.myspringmvc.web.method.HandlerMethod;
import org.myspringmvc.web.servlet.HandlerAdapter;
import org.myspringmvc.web.servlet.ModelAndView;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * @author 莫磊
 * @date 2025/8/12
 * @description 为requestMapping注解创建的适配器
 */
public class RequestMappingHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 判断这个handlerMethod是否使用了requestMapping注解
            return handlerMethod.getMethod().isAnnotationPresent(RequestMapping.class);
        }
        return false;
    }

    /**
     * 调用处理器方法返回ModelAndView
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        ModelAndView mv = new ModelAndView();
        // 执行handlerMethod方法，获取返回值，设置视图名

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        // 获取controller
        Object controller = handlerMethod.getHandler();
        Method method = handlerMethod.getMethod();
        // 获取方法的参数
        Parameter[] parameters = method.getParameters();
        Object[] args = new Object[parameters.length];
        // 根据参数名称从request中获取参数值
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            // 判断是否为基础类型的参数类型
            if (ObjectUtil.isBaseType(parameter.getType())) {
                args[i] = ObjectUtil.convertParam(request.getParameter(parameter.getName()), parameter.getType());
            } else {
                // 判断为对象参数
                // 获取对用的class对象
                Class<?> clazz = parameter.getType();
                Object obj = clazz.getDeclaredConstructor().newInstance();
                for (Field field : clazz.getDeclaredFields()) {
                    // 获取参数名称
                    String attributeName = field.getName();
                    // 获取参数值
                    String attributeValue = (String) request.getParameter(attributeName);

                    ObjectUtil.setFieldForBean(obj, attributeName, attributeValue);
                }
                args[i] = obj;
            }
        }

        // 执行方法，默认返回的都是ModelAndView
        Object result = method.invoke(controller, args);

        if (result instanceof ModelAndView) {
            mv = (ModelAndView) result;
        }
        return mv;
    }
}
